#include "Thread.hpp"
#include "BlockQueue.hpp"
#include <vector>
#include <string>
#include <stdlib.h>
#include <unistd.h>
#define CAPSIZE 5
using ValType = int;
void Consumer(BlockQueue<ValType>* bq)
{
    while(true)
    {
        int val;
        bq->dequeue(val);
        std::cout << "get a data :" << val << std::endl;
    }
}
void Productor(BlockQueue<ValType>* bq)
{
    while(true)
    {
       int val = rand()%100;
       bq->enqueue(val);
       std::cout << val << " enqueue success!" << std::endl;
       sleep(1);
    }
}
void StartCommon(std::vector<Thread<BlockQueue<ValType>*>>& v,int num 
,std::string name_prefix , func_t<BlockQueue<ValType>*> func 
, BlockQueue<ValType>* bq)
{

    for(int i = 0 ; i < num ; ++i)
    {
       std::string name = name_prefix + std::to_string(i+1);
       Thread<BlockQueue<ValType>*> t(name,func,bq);
       v.push_back(t);
    }
}
void Start(std::vector<Thread<BlockQueue<ValType>*>>& threads)
{
    for(auto& thread : threads)
    {
        thread.Start();
    }
}

void StartProductor(std::vector<Thread<BlockQueue<ValType>*>>& v , int num , BlockQueue<ValType>* bq)
{
    StartCommon(v,num,"productor-",Productor,bq);
}
void StartConsumer(std::vector<Thread<BlockQueue<ValType>*>>& v , int num , BlockQueue<ValType>* bq)
{
    StartCommon(v,num,"consumer-",Consumer,bq);
}
void WaitAll(std::vector<Thread<BlockQueue<ValType>*>>& v)
{
    for(auto t : v)
    {
        t.join();
    }
}
int main()
{
    // Thread<int> t("",Print,int());
    // t.Start();
    BlockQueue<ValType>* q = new BlockQueue<ValType>(CAPSIZE);
    int productor_num = 1;
    int consumer_num = 1;
    std::vector<Thread<BlockQueue<ValType>*>> threads;
    StartProductor(threads,productor_num,q);
    StartConsumer(threads,consumer_num,q);
    Start(threads);
    WaitAll(threads);
    // t.join();
    return 0;
}
